#include "QtWidgetsApplication1.h"

#include <QFileDialog>


/**
 * @brief QtWidgetsApplication1::QtWidgetsApplication1
 * @param parent
 *
 * 关键字提示弹窗参考于Qt官方教程 googlesuggest这个例子
 */


QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
    : QMainWindow(parent),ui(new Ui::QtWidgetsApplication1Class)
{
    ui->setupUi(this);
    highLight = new HighLight (ui->plainTextEdit->document());
    connectPlainText();

    keyword = new KeyWord();
    intiField (keyword->getKeywordDictionary (),keyword->getColors ());

    pop = new QTreeWidget;
    pop->setWindowFlags (Qt::Popup);
    pop->setFocusPolicy(Qt::NoFocus);
    pop->setFocusProxy(ui->plainTextEdit);
    pop->setMouseTracking(true);
    pop->setColumnCount(2);
    pop->setUniformRowHeights(true);
    pop->setRootIsDecorated(false);
    pop->setEditTriggers(QTreeWidget::NoEditTriggers);
    pop->setSelectionBehavior(QTreeWidget::SelectRows);
    pop->setFrameStyle(QFrame::Box | QFrame::Plain);
    pop->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    pop->header()->hide();
    pop->installEventFilter (this);

}

QtWidgetsApplication1::~QtWidgetsApplication1 ()
{
    delete highLight;
    delete keyword;
    delete pop;
    delete ui;
}

void QtWidgetsApplication1::do_cursorChanged ()
{
    qDebug()<<"cursorchanged:";
}

void QtWidgetsApplication1::do_textChanged ()
{
    qDebug () << "text changed";
    popFrame ();
}

void QtWidgetsApplication1::connectPlainText()
{
    connect (ui->plainTextEdit ,&QPlainTextEdit::textChanged,this,&QtWidgetsApplication1::do_textChanged);
}

void QtWidgetsApplication1::keyPressEvent(QKeyEvent *event)
{
    QPlainTextEdit *textEdit = ui->plainTextEdit;
    if (event->modifiers () == Qt::ControlModifier && event->key () == Qt::Key_Tab) {
        if (textEdit->textCursor ().atStart ()) {
            return;
        }
        QTextCursor cursor = textEdit->textCursor();
        QTextBlock block = cursor.block();
        int startPosition = cursor.position ();
        cursor.setPosition (5);
        for (int i = 1; i < 5; ++i) {
            if (block.text ().at (0) == '\t') {
                cursor.setPosition (0);
                cursor.deleteChar ();
                cursor.setPosition (startPosition-1);
                break;
            }
        }
    }else if (event->modifiers () == Qt::ControlModifier && event->key () == Qt::Key_R)
    {
        this->setStyleSheet (ui->plainTextEdit->document ()->toPlainText ());
    }
}

/**
 * @brief QtWidgetsApplication1::popFrame 弹出关键字提示窗口
 */
void QtWidgetsApplication1::popFrame()
{
    cursorText = ui->plainTextEdit->textCursor ().block ().text ();
    int cursorIndex = ui->plainTextEdit->textCursor ().position ();
    qDebug()<<"cursor:"<<cursorText;
    qDebug()<<"cursor:"<<cursorIndex;
    if (cursorIndex == 0 | cursorText == "") {
        return;
    }
    pop->setUpdatesEnabled(false);
    pop->clear ();
    if(getMatchItems(cursorText)){
        if (pop->topLevelItemCount ()!=0) {
            pop->setCurrentItem(pop->topLevelItem(0));
            pop->move(ui->plainTextEdit->mapToGlobal(ui->plainTextEdit->cursorRect ().bottomLeft ()));
            pop->resizeColumnToContents(1);
            pop->resizeColumnToContents(0);
            pop->setFocus();
            pop->show ();
        }
    }
    pop->setUpdatesEnabled(true);
}
/**
 * @brief QtWidgetsApplication1::getMatchItems 在stylehash里面匹配的关键字
 * @param text 要查找的字符串
 * @return 返回在stylehash里面有没有找到相似的关键字
 */
bool QtWidgetsApplication1::getMatchItems(QString text)
{
    QStringList temp = text.split (" ",Qt::SkipEmptyParts);
    if(temp.isEmpty ()|text.back () == ' '){
        return false;
    }
    lastString = temp.back ();
    lastString = lastString.trimmed ();
    qDebug()<<"lastString:"<<lastString;
    if(!lastString.length ()==0){
        QChar backChar = lastString.back ();
        if(backChar.isSpace ()){
            return false;
        }
        if (backChar== '{'|backChar=='}' |backChar==':') {
            return false;
        }
    }else {
        return false;
    }
    QStringList list;
    QHash <QString,QIcon> &icons = keyword->getIcons ();
    isAdd = false;
    foreach (QString key ,keyword->getKeywordDictionary ().keys ())
    {
        list = keyword->getKeywordDictionary ()[key];
        for (int i = 0; i < list.size (); ++i) {
            QRegularExpression expression("^"+lastString,QRegularExpression::CaseInsensitiveOption);
            QRegularExpressionMatchIterator reMatch = expression.globalMatch (list.at (i));
            while (reMatch.hasNext ())
            {
                isAdd = true;
                auto matchItem = new QTreeWidgetItem(pop);
                reMatch.next ();
                matchItem->setIcon (0,icons.value (key));
                matchItem->setText (1,list.at (i));
                qDebug()<<"matchs:"<< list.at (i);
            }
        }
    }
    return true;
}

/**
 * @brief QtWidgetsApplication1::eventFilter 其他控件委托本对象进行监听它所发生的事件
 * @param watched 发生事件的对象
 * @param event 发生了什么事件
 * @return 表示事件是否被处理,返回false就会被其他控件处理
 */
bool QtWidgetsApplication1::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == pop){
        if (event->type() == QEvent::MouseButtonPress) {
            pop->hide();
            ui->plainTextEdit->setFocus();
            return true;
        }
        if (event->type() == QEvent::KeyPress) {
            bool consumed = false;
            int key = static_cast<QKeyEvent*>(event)->key();
            switch (key) {
            case Qt::Key_Enter:
            case Qt::Key_Return:
                choiced();
                consumed = true;
                break;

            case Qt::Key_Escape:
                ui->plainTextEdit->setFocus();
                pop->hide();
                consumed = true;
                break;

            case Qt::Key_Up:
            case Qt::Key_Down:
            case Qt::Key_Home:
            case Qt::Key_End:
            case Qt::Key_PageUp:
            case Qt::Key_PageDown:
                break;

            default:
                ui->plainTextEdit->setFocus();
                //这下面这两句不加,就会在有提示的情况下输入不了字
                QObject * textEdit = qobject_cast<QPlainTextEdit *>(ui->plainTextEdit);
                textEdit->event (event);
                pop->hide();
                break;
            }
            return consumed;
        }
    }
    return false;
}

/**
 * @brief QtWidgetsApplication1::choiced 模糊查询结果弹出后，按下回车后的动作
 */
void QtWidgetsApplication1::choiced()
{
    qDebug()<<"choice:"<<cursorText;
    ui->plainTextEdit->setFocus();
    if (!isAdd) {
        return;
    }
    QTreeWidgetItem * item = pop->currentItem ();
    QString insertString;
    QIcon itemType = item->icon (0);
    QIcon userIcon = keyword->getIcons ()["user"];
    qDebug()<<"type:"<<itemType.cacheKey ();
    qDebug()<<"user:"<<userIcon.cacheKey ();
    if (itemType.cacheKey ()== userIcon.cacheKey ()) {
        insertString = keyword->userTable[item->text (1)];
    }else{
        insertString = item->text (1);
    }
    qDebug()<<"lastChoice:"<<insertString;
    if(insertString.isEmpty ()){
        return;
    }
    if (item) {
        QTextCursor current = ui->plainTextEdit->textCursor ();
        int moveBefore = current.position ();
        QString text = current.block ().text ();
        int textLenght =text.length ();
        while (textLenght>0) {
            moveBefore --;
            textLenght --;
            if (textLenght<-1) {
                break;
            }
            if (text.at (textLenght) == ' ' | text.at (textLenght) == ':'|text.at (textLenght)== '\t') {
                moveBefore ++;
                qDebug()<<"break text lenght:"<<textLenght;
                break;
            }
        }
        current.setPosition (moveBefore,QTextCursor::KeepAnchor);
        current.removeSelectedText ();
        current.insertText (insertString);
    }
    pop->hide();
}


/**
 * @brief QtWidgetsApplication1::intiField 加载关键字
 * @param styleHash 关键字
 * @param colors 颜色
 */
void QtWidgetsApplication1::intiField (QHash <QString,QStringList> &styleHash,QHash<QString,QColor> &colors)
{
    QHashIterator<QString,QStringList> styleInterator(styleHash);
    while (styleInterator.hasNext ()) {
        styleInterator.next ();
        QColor color = colors[styleInterator.key ()];
        for (QString content : styleInterator.value ()) {
            highLight->setTextColor (content,color);
        }
    }
}



void QtWidgetsApplication1::on_actionOpenFile_triggered()
{
    QString currentPath = QApplication::applicationDirPath();
    QString aFilePath = QFileDialog::getOpenFileName(this,"select data file",currentPath,"data file(*.qss);;all file(*)");
    if (aFilePath.isEmpty()) {
        return;
    }
    QFile file(aFilePath);
    if (file.open(QIODevice::ReadOnly|QIODevice::Text)) {
        QTextStream aStream(&file);
        ui->plainTextEdit->clear();
        while (!aStream.atEnd()) {
            QString line = aStream.readLine();
            ui->plainTextEdit->appendPlainText(line);
        }
        file.close();
    }
}



void QtWidgetsApplication1::on_actionOutputFile_triggered()
{
    QString currentPath = QApplication::applicationDirPath();
    QString aFilePath = QFileDialog::getExistingDirectory (this,"选择要保存到的文件夹",currentPath);
    if (aFilePath.isEmpty()) {
        return;
    }
    QDateTime currentTimestamp = QDateTime::currentDateTime();
    QFile file(aFilePath+"\\"+QString("%1").arg (currentTimestamp.currentDateTime ().toMSecsSinceEpoch ())+".qss");
    qDebug()<<"file path:"<<file.fileName ();
    if (file.open(QIODevice::WriteOnly|QIODevice::Text)) {
        QTextStream aStream(&file);
        aStream<<ui->plainTextEdit->toPlainText ();
        file.close();
    }
}

void QtWidgetsApplication1::on_actionRun_triggered()
{
    this->setStyleSheet (ui->plainTextEdit->document ()->toPlainText ());
}



